// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

#include <VisualCueInfo.h>
#include <DataNode.h>

//
// Enum conversion methods for VisualCueInfo::CueType
//

static const char *CueType_strings[] = {
"PickPoint", "RefLine", "Unknown"
};

std::string
VisualCueInfo::CueType_ToString(VisualCueInfo::CueType t)
{
    int index = int(t);
    if(index < 0 || index >= 3) index = 0;
    return CueType_strings[index];
}

std::string
VisualCueInfo::CueType_ToString(int t)
{
    int index = (t < 0 || t >= 3) ? 0 : t;
    return CueType_strings[index];
}

bool
VisualCueInfo::CueType_FromString(const std::string &s, VisualCueInfo::CueType &val)
{
    val = VisualCueInfo::PickPoint;
    for(int i = 0; i < 3; ++i)
    {
        if(s == CueType_strings[i])
        {
            val = (CueType)i;
            return true;
        }
    }
    return false;
}

// ****************************************************************************
// Method: VisualCueInfo::VisualCueInfo
//
// Purpose:
//   Init utility for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void VisualCueInfo::Init()
{
    cueType = Unknown;
    showLabel = false;
    lineWidth = 0;
    opacity = 1;
    highlightColor[0] = 0;
    highlightColor[1] = 1;
    highlightColor[2] = 0;
    showHighlight = false;

    VisualCueInfo::SelectAll();
}

// ****************************************************************************
// Method: VisualCueInfo::VisualCueInfo
//
// Purpose:
//   Copy utility for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void VisualCueInfo::Copy(const VisualCueInfo &obj)
{
    points = obj.points;
    cueType = obj.cueType;
    color = obj.color;
    glyphType = obj.glyphType;
    label = obj.label;
    showLabel = obj.showLabel;
    lineWidth = obj.lineWidth;
    opacity = obj.opacity;
    highlightColor[0] = obj.highlightColor[0];
    highlightColor[1] = obj.highlightColor[1];
    highlightColor[2] = obj.highlightColor[2];

    showHighlight = obj.showHighlight;

    VisualCueInfo::SelectAll();
}

// Type map format string
const char *VisualCueInfo::TypeMapFormatString = VISUALCUEINFO_TMFS;
const AttributeGroup::private_tmfs_t VisualCueInfo::TmfsStruct = {VISUALCUEINFO_TMFS};


// ****************************************************************************
// Method: VisualCueInfo::VisualCueInfo
//
// Purpose:
//   Default constructor for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

VisualCueInfo::VisualCueInfo() :
    AttributeSubject(VisualCueInfo::TypeMapFormatString),
    color(0, 0, 0)
{
    VisualCueInfo::Init();
}

// ****************************************************************************
// Method: VisualCueInfo::VisualCueInfo
//
// Purpose:
//   Constructor for the derived classes of VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

VisualCueInfo::VisualCueInfo(private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs),
    color(0, 0, 0)
{
    VisualCueInfo::Init();
}

// ****************************************************************************
// Method: VisualCueInfo::VisualCueInfo
//
// Purpose:
//   Copy constructor for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

VisualCueInfo::VisualCueInfo(const VisualCueInfo &obj) :
    AttributeSubject(VisualCueInfo::TypeMapFormatString)
{
    VisualCueInfo::Copy(obj);
}

// ****************************************************************************
// Method: VisualCueInfo::VisualCueInfo
//
// Purpose:
//   Copy constructor for derived classes of the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

VisualCueInfo::VisualCueInfo(const VisualCueInfo &obj, private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs)
{
    VisualCueInfo::Copy(obj);
}

// ****************************************************************************
// Method: VisualCueInfo::~VisualCueInfo
//
// Purpose:
//   Destructor for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

VisualCueInfo::~VisualCueInfo()
{
    // nothing here
}

// ****************************************************************************
// Method: VisualCueInfo::operator =
//
// Purpose:
//   Assignment operator for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

VisualCueInfo&
VisualCueInfo::operator = (const VisualCueInfo &obj)
{
    if (this == &obj) return *this;

    VisualCueInfo::Copy(obj);

    return *this;
}

// ****************************************************************************
// Method: VisualCueInfo::operator ==
//
// Purpose:
//   Comparison operator == for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
VisualCueInfo::operator == (const VisualCueInfo &obj) const
{
    // Compare the highlightColor arrays.
    bool highlightColor_equal = true;
    for(int i = 0; i < 3 && highlightColor_equal; ++i)
        highlightColor_equal = (highlightColor[i] == obj.highlightColor[i]);

    // Create the return value
    return ((points == obj.points) &&
            (cueType == obj.cueType) &&
            (color == obj.color) &&
            (glyphType == obj.glyphType) &&
            (label == obj.label) &&
            (showLabel == obj.showLabel) &&
            (lineWidth == obj.lineWidth) &&
            (opacity == obj.opacity) &&
            highlightColor_equal &&
            (showHighlight == obj.showHighlight));
}

// ****************************************************************************
// Method: VisualCueInfo::operator !=
//
// Purpose:
//   Comparison operator != for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
VisualCueInfo::operator != (const VisualCueInfo &obj) const
{
    return !(this->operator == (obj));
}

// ****************************************************************************
// Method: VisualCueInfo::TypeName
//
// Purpose:
//   Type name method for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const std::string
VisualCueInfo::TypeName() const
{
    return "VisualCueInfo";
}

// ****************************************************************************
// Method: VisualCueInfo::CopyAttributes
//
// Purpose:
//   CopyAttributes method for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
VisualCueInfo::CopyAttributes(const AttributeGroup *atts)
{
    if(TypeName() != atts->TypeName())
        return false;

    // Call assignment operator.
    const VisualCueInfo *tmp = (const VisualCueInfo *)atts;
    *this = *tmp;

    return true;
}

// ****************************************************************************
// Method: VisualCueInfo::CreateCompatible
//
// Purpose:
//   CreateCompatible method for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
VisualCueInfo::CreateCompatible(const std::string &tname) const
{
    AttributeSubject *retval = 0;
    if(TypeName() == tname)
        retval = new VisualCueInfo(*this);
    // Other cases could go here too.

    return retval;
}

// ****************************************************************************
// Method: VisualCueInfo::NewInstance
//
// Purpose:
//   NewInstance method for the VisualCueInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
VisualCueInfo::NewInstance(bool copy) const
{
    AttributeSubject *retval = 0;
    if(copy)
        retval = new VisualCueInfo(*this);
    else
        retval = new VisualCueInfo;

    return retval;
}

// ****************************************************************************
// Method: VisualCueInfo::SelectAll
//
// Purpose:
//   Selects all attributes.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
VisualCueInfo::SelectAll()
{
    Select(ID_points,         (void *)&points);
    Select(ID_cueType,        (void *)&cueType);
    Select(ID_color,          (void *)&color);
    Select(ID_glyphType,      (void *)&glyphType);
    Select(ID_label,          (void *)&label);
    Select(ID_showLabel,      (void *)&showLabel);
    Select(ID_lineWidth,      (void *)&lineWidth);
    Select(ID_opacity,        (void *)&opacity);
    Select(ID_highlightColor, (void *)highlightColor, 3);
    Select(ID_showHighlight,  (void *)&showHighlight);
}

///////////////////////////////////////////////////////////////////////////////
// Set property methods
///////////////////////////////////////////////////////////////////////////////

void
VisualCueInfo::SetPoints(const doubleVector &points_)
{
    points = points_;
    Select(ID_points, (void *)&points);
}

void
VisualCueInfo::SetCueType(VisualCueInfo::CueType cueType_)
{
    cueType = cueType_;
    Select(ID_cueType, (void *)&cueType);
}

void
VisualCueInfo::SetColor(const ColorAttribute &color_)
{
    color = color_;
    Select(ID_color, (void *)&color);
}

void
VisualCueInfo::SetGlyphType(const std::string &glyphType_)
{
    glyphType = glyphType_;
    Select(ID_glyphType, (void *)&glyphType);
}

void
VisualCueInfo::SetLabel(const std::string &label_)
{
    label = label_;
    Select(ID_label, (void *)&label);
}

void
VisualCueInfo::SetShowLabel(bool showLabel_)
{
    showLabel = showLabel_;
    Select(ID_showLabel, (void *)&showLabel);
}

void
VisualCueInfo::SetLineWidth(int lineWidth_)
{
    lineWidth = lineWidth_;
    Select(ID_lineWidth, (void *)&lineWidth);
}

void
VisualCueInfo::SetOpacity(double opacity_)
{
    opacity = opacity_;
    Select(ID_opacity, (void *)&opacity);
}

void
VisualCueInfo::SetHighlightColor(const float *highlightColor_)
{
    highlightColor[0] = highlightColor_[0];
    highlightColor[1] = highlightColor_[1];
    highlightColor[2] = highlightColor_[2];
    Select(ID_highlightColor, (void *)highlightColor, 3);
}

void
VisualCueInfo::SetShowHighlight(bool showHighlight_)
{
    showHighlight = showHighlight_;
    Select(ID_showHighlight, (void *)&showHighlight);
}

///////////////////////////////////////////////////////////////////////////////
// Get property methods
///////////////////////////////////////////////////////////////////////////////

const doubleVector &
VisualCueInfo::GetPoints() const
{
    return points;
}

doubleVector &
VisualCueInfo::GetPoints()
{
    return points;
}

VisualCueInfo::CueType
VisualCueInfo::GetCueType() const
{
    return CueType(cueType);
}

const ColorAttribute &
VisualCueInfo::GetColor() const
{
    return color;
}

ColorAttribute &
VisualCueInfo::GetColor()
{
    return color;
}

const std::string &
VisualCueInfo::GetGlyphType() const
{
    return glyphType;
}

std::string &
VisualCueInfo::GetGlyphType()
{
    return glyphType;
}

const std::string &
VisualCueInfo::GetLabel() const
{
    return label;
}

std::string &
VisualCueInfo::GetLabel()
{
    return label;
}

bool
VisualCueInfo::GetShowLabel() const
{
    return showLabel;
}

int
VisualCueInfo::GetLineWidth() const
{
    return lineWidth;
}

double
VisualCueInfo::GetOpacity() const
{
    return opacity;
}

const float *
VisualCueInfo::GetHighlightColor() const
{
    return highlightColor;
}

float *
VisualCueInfo::GetHighlightColor()
{
    return highlightColor;
}

bool
VisualCueInfo::GetShowHighlight() const
{
    return showHighlight;
}

///////////////////////////////////////////////////////////////////////////////
// Select property methods
///////////////////////////////////////////////////////////////////////////////

void
VisualCueInfo::SelectPoints()
{
    Select(ID_points, (void *)&points);
}

void
VisualCueInfo::SelectColor()
{
    Select(ID_color, (void *)&color);
}

void
VisualCueInfo::SelectGlyphType()
{
    Select(ID_glyphType, (void *)&glyphType);
}

void
VisualCueInfo::SelectLabel()
{
    Select(ID_label, (void *)&label);
}

void
VisualCueInfo::SelectHighlightColor()
{
    Select(ID_highlightColor, (void *)highlightColor, 3);
}

///////////////////////////////////////////////////////////////////////////////
// Keyframing methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: VisualCueInfo::GetFieldName
//
// Purpose:
//   This method returns the name of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
VisualCueInfo::GetFieldName(int index) const
{
    switch (index)
    {
    case ID_points:         return "points";
    case ID_cueType:        return "cueType";
    case ID_color:          return "color";
    case ID_glyphType:      return "glyphType";
    case ID_label:          return "label";
    case ID_showLabel:      return "showLabel";
    case ID_lineWidth:      return "lineWidth";
    case ID_opacity:        return "opacity";
    case ID_highlightColor: return "highlightColor";
    case ID_showHighlight:  return "showHighlight";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: VisualCueInfo::GetFieldType
//
// Purpose:
//   This method returns the type of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeGroup::FieldType
VisualCueInfo::GetFieldType(int index) const
{
    switch (index)
    {
    case ID_points:         return FieldType_doubleVector;
    case ID_cueType:        return FieldType_enum;
    case ID_color:          return FieldType_color;
    case ID_glyphType:      return FieldType_string;
    case ID_label:          return FieldType_string;
    case ID_showLabel:      return FieldType_bool;
    case ID_lineWidth:      return FieldType_linewidth;
    case ID_opacity:        return FieldType_opacity;
    case ID_highlightColor: return FieldType_floatArray;
    case ID_showHighlight:  return FieldType_bool;
    default:  return FieldType_unknown;
    }
}

// ****************************************************************************
// Method: VisualCueInfo::GetFieldTypeName
//
// Purpose:
//   This method returns the name of a field type given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
VisualCueInfo::GetFieldTypeName(int index) const
{
    switch (index)
    {
    case ID_points:         return "doubleVector";
    case ID_cueType:        return "enum";
    case ID_color:          return "color";
    case ID_glyphType:      return "string";
    case ID_label:          return "string";
    case ID_showLabel:      return "bool";
    case ID_lineWidth:      return "linewidth";
    case ID_opacity:        return "opacity";
    case ID_highlightColor: return "floatArray";
    case ID_showHighlight:  return "bool";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: VisualCueInfo::FieldsEqual
//
// Purpose:
//   This method compares two fields and return true if they are equal.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
VisualCueInfo::FieldsEqual(int index_, const AttributeGroup *rhs) const
{
    const VisualCueInfo &obj = *((const VisualCueInfo*)rhs);
    bool retval = false;
    switch (index_)
    {
    case ID_points:
        {  // new scope
        retval = (points == obj.points);
        }
        break;
    case ID_cueType:
        {  // new scope
        retval = (cueType == obj.cueType);
        }
        break;
    case ID_color:
        {  // new scope
        retval = (color == obj.color);
        }
        break;
    case ID_glyphType:
        {  // new scope
        retval = (glyphType == obj.glyphType);
        }
        break;
    case ID_label:
        {  // new scope
        retval = (label == obj.label);
        }
        break;
    case ID_showLabel:
        {  // new scope
        retval = (showLabel == obj.showLabel);
        }
        break;
    case ID_lineWidth:
        {  // new scope
        retval = (lineWidth == obj.lineWidth);
        }
        break;
    case ID_opacity:
        {  // new scope
        retval = (opacity == obj.opacity);
        }
        break;
    case ID_highlightColor:
        {  // new scope
        // Compare the highlightColor arrays.
        bool highlightColor_equal = true;
        for(int i = 0; i < 3 && highlightColor_equal; ++i)
            highlightColor_equal = (highlightColor[i] == obj.highlightColor[i]);

        retval = highlightColor_equal;
        }
        break;
    case ID_showHighlight:
        {  // new scope
        retval = (showHighlight == obj.showHighlight);
        }
        break;
    default: retval = false;
    }

    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// User-defined methods.
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: VisualCueInfo::SetPointF
//
// Purpose: Set a specific entry (the ith point) in the vector of
//          points for this VisualCueInfo.
//
//          Points are stored in a double vector. Each successive group
//          of 3 entries in the vector is a single point.
//
// Programmer: Mark C. Miller
// Creation:   June 3, 2004
//
// ****************************************************************************
void
VisualCueInfo::SetPointF(int i, const float *pt)
{
    // extend vector of points as necessary
    while ((int)points.size() < 3*(i+1))
        points.push_back(0.0);

    points[3*i+0] = pt[0];
    points[3*i+1] = pt[1];
    points[3*i+2] = pt[2];

    Select(0,(void*)&points);
}

// ****************************************************************************
// Method: VisualCueInfo::GetPointF
//
// Purpose: Get a specific entry (the ith point) in the vector of
//          points for this VisualCueInfo.
//
//          Return false if an ith entry does not exist
///
// Programmer: Mark C. Miller
// Creation:   June 3, 2004
//
// ****************************************************************************
bool
VisualCueInfo::GetPointF(int i, float *pt) const
{
    if ((int)points.size() < 3*i)
        return false;

    pt[0] = (float) points[3*i+0];
    pt[1] = (float) points[3*i+1];
    pt[2] = (float) points[3*i+2];

    return true;
}

void
VisualCueInfo::SetFromP(const PickAttributes *pa)
{
    if (pa == 0)
        return;

    SetCueType(PickPoint);
    SetPointD(0,pa->GetPickPoint());
    SetLabel(pa->GetPickLetter());
    SetShowLabel(pa->GetShowPickLetter());
    float hColor[3];
    for (int i = 0; i < 3; ++i)
        hColor[i] = pa->GetPickHighlightColor()[i] / 255.0;
    showHighlight = pa->GetShowPickHighlight();
    SetHighlightColor(hColor);
    if ((pa->GetPickType() != PickAttributes::Zone) &&
        (pa->GetPickType() != PickAttributes::DomainZone))
        SetGlyphType("Square");
    const doubleVector cellCoords = pa->GetCellCoordinates();
    const int numPoints = cellCoords.size() / 3;
    for(int i = 0; i < numPoints; ++i)
    {
        // First point is attachment point, so offset by 1
        int pid = (i + 1);
        SetPointD(pid,&cellCoords[i*3]);
    }
}

void
VisualCueInfo::SetFromL(const Line *line)
{
    if (line == 0)
        return;

    SetCueType(RefLine);
    SetPointD(0,line->GetPoint1());
    SetPointD(1,line->GetPoint2());
    SetLabel(line->GetDesignator());
    SetShowLabel(line->GetReflineLabels());
    SetLineWidth(line->GetLineWidth());
    SetColor(line->GetColor());
}

// ****************************************************************************
// Method: VisualCueInfo::SetPointD
//
// Purpose: Set a specific entry (the ith point) in the vector of
//          points for this VisualCueInfo.
//
//          Points are stored in a double vector. Each successive group
//          of 3 entries in the vector is a single point.
//
// Programmer: Mark C. Miller
// Creation:   June 3, 2004
//
// ****************************************************************************
void
VisualCueInfo::SetPointD(int i, const double *pt)
{
    // extend vector of points as necessary
    while ((int)points.size() < 3*(i+1))
        points.push_back(0.0);

    points[3*i+0] = pt[0];
    points[3*i+1] = pt[1];
    points[3*i+2] = pt[2];

    Select(0,(void*)&points);
}

// ****************************************************************************
// Method: VisualCueInfo::GetPointD
//
// Purpose: Get a specific entry (the ith point) in the vector of
//          points for this VisualCueInfo.
//
//          Return false if an ith entry does not exist
///
// Programmer: Mark C. Miller
// Creation:   June 3, 2004
//
// ****************************************************************************
bool
VisualCueInfo::GetPointD(int i, double *pt) const
{
    if ((int)points.size() < 3*i)
        return false;

    pt[0] = points[3*i+0];
    pt[1] = points[3*i+1];
    pt[2] = points[3*i+2];

    return true;
}

